#include "Grito.h"
#include "Vectores.h"
#include "Obstacle.h"
#include "CApp.h"

#include <iostream>
#include <SDL/SDL.h>
#include <SDL/SDL_gfxPrimitives.h>

Grito::Grito(float x, float y,
    long duration, float recorrido){
  this->position[0] = x;
  this->position[1] = y;

  this->recorrido = 500;
  // this->recorrido = recorrido;
  this->acumuladoRecorrido = 0;

  this->duration = 1300;
  // this->duration = duration;
  // this->duration = 10000;
  this->oldTime = SDL_GetTicks();
  this->oldTimeTrue = SDL_GetTicks() - 400;

//this->segmentos = 32;
  this->segmentos = 128;

  vx = (float *)malloc(sizeof(float)*segmentos);
  vy = (float *)malloc(sizeof(float)*segmentos);
  acumulados = (float *)malloc(sizeof(float)*segmentos);
  for(int i=0; i<segmentos; i++){
    acumulados[i] = 0;
  }

  this->vel = this->recorrido/this->duration;

  for(int i=0; i<segmentos; i++){
    float angulo = i * (2*M_PI)/float(segmentos);
    float *vector = asVector(angulo);

//  cout << "Angulo: " << angulo << endl;
//  cout << vector[0] << " " << vector[1] << endl;

    vx[i] = vector[0];
    vy[i] = vector[1];

    free(vector);
  }
}

Grito::~Grito(){
  free(vx);
  free(vy);
  free(acumulados);
}

void Grito::OnLoop(){
}

bool Grito::hasExpired(){
  long current = SDL_GetTicks();
  bool resp = false;

  if(current-oldTimeTrue>duration){
    resp = true;
  }

  return resp;
}

void Grito::OnRender(SDL_Surface* display){
  int i;
  long currentTime = SDL_GetTicks();
  float currentRecorrido = float(currentTime-oldTime)/duration;
  Sint16 *tempX = (Sint16 *)malloc(sizeof(Sint16)*segmentos);
  Sint16 *tempY = (Sint16 *)malloc(sizeof(Sint16)*segmentos);
  acumuladoRecorrido += this->recorrido*currentRecorrido;

  for(i=0; i<segmentos; i++){
    float vector[3];
    acumulados[i] += this->recorrido*currentRecorrido;

    vector[0] = vx[i] * acumulados[i] + position[0];
    vector[1] = vy[i] * acumulados[i] + position[1];

    // Revisamos colision
    float _vel[3] = {
      vx[i] * recorrido/duration,
      vy[i] * recorrido/duration,
      0};

    float _pos[3] = {
      vx[i] * acumulados[i] + position[0],
      vy[i] * acumulados[i] + position[1], 0};
    float*_current = (float *) malloc(sizeof(float)*3);
    float *I = (float *) malloc(sizeof(float)*3);
    float *N = (float *) malloc(sizeof(float)*3);

    for(int k=0, n2=obstacle.size(); k<n2; k++){
      if( obstacle[k]->collideWith(
            _pos, _vel, &_current, &I, &N)){
        // DEBUG
        // cout << "Choco" << endl;
        acumulados[i] -= this->recorrido*currentRecorrido;
        break;
      }
    }
    free(_current);
    free(I);
    free(N);
    // END Collide

    if(theApp._flag_showSonido){
      filledEllipseRGBA(display,
          fixX(vector[0]), fixY(vector[1]),
          3, 3,
          0, 0, 40, 128
          );
    }
    tempX[i] = fixX( (Sint16)vector[0] );
    tempY[i] = fixY( (Sint16)vector[1] );
  }

  if(theApp._flag_showSonido){
    filledPolygonRGBA(display,
        tempX, tempY, segmentos,
        20, 20, 220, 80);
  }

  this->oldTime = currentTime;
  free(tempX);
  free(tempY);
}

bool Grito::isIn(const float P[3]){
  int i;
  long currentTime = SDL_GetTicks();
  float currentRecorrido = float(currentTime-oldTime)/duration;
  Sint16 *tempX = (Sint16 *)malloc(sizeof(Sint16)*segmentos);
  Sint16 *tempY = (Sint16 *)malloc(sizeof(Sint16)*segmentos);
  acumuladoRecorrido += this->recorrido*currentRecorrido;

  for(i=0; i<segmentos; i++){
    float vector[3];
    acumulados[i] += this->recorrido*currentRecorrido;

    vector[0] = vx[i] * acumulados[i] + position[0];
    vector[1] = vy[i] * acumulados[i] + position[1];

    // Revisamos colision
    float _vel[3] = {
      vx[i] * recorrido/duration,
      vy[i] * recorrido/duration,
      0};

    float _pos[3] = {
      vx[i] * acumulados[i] + position[0],
      vy[i] * acumulados[i] + position[1], 0};
    float*_current = (float *) malloc(sizeof(float)*3);
    float *I = (float *) malloc(sizeof(float)*3);
    float *N = (float *) malloc(sizeof(float)*3);

    for(int k=0, n2=obstacle.size(); k<n2; k++){
      if( obstacle[k]->collideWith(
            _pos, _vel, &_current, &I, &N)){
        // DEBUG
        // cout << "Choco" << endl;
        acumulados[i] -= this->recorrido*currentRecorrido;
        break;
      }
    }
    free(_current);
    free(I);
    free(N);
    // END Collide

    tempX[i] = (Sint16)vector[0];
    tempY[i] = (Sint16)vector[1];
  }

  for(i=0; i<segmentos; i++){
    float vector[3] = {tempX[i], tempY[i], 0};
    float vector2[3] = {
      tempX[(i+1)%segmentos],
      tempY[(i+1)%segmentos], 0};

    if(pointIntTriangle(P, vector, vector2, position))
        return true;
  }

  free(tempX);
  free(tempY);

  return false;
}

